<?php if(! defined('HAS_POWER') ) exit('无权访问!');
/**
==============================================================================
 * Class FormComponent GracePHP的表单模型类
 * @author 肖永标
 * @date 2014-11-30
==============================================================================
 */
class FormComponent extends Component {

    /**
     * @var FormComponent $ins 保存表单模型实例
     */
    public static $ins;

    /**
     * @var mixed $val 表单控件的值
     */
    public $val;

    /**
     * @var string $label 表单控件的标签
     */
    public $label;

    /**
     * @var string $field 表单控件的字段名称
     */
    public $field;

    /**
     * @var array $errMsg 表单的错误信息集合
     */
    private $errMsg = array();

    /**
     * @var array $config 表单验证配置数组
     */
    private $config = array();

    /**
     * @var string $csrf 防跨站伪造请求的加密字符串
     */
    private $csrf;

    private function __construct() {}
    private function __clone() {}

    /** 单例模式 一个控制器只需要一个实例
     * @return FormComponent
     */
    public static function getIns()
    {
        if(!self::$ins instanceof FormComponent)
            self::$ins = new FormComponent();

        return self::$ins;
    }


    /**表单是否发生POST请求
     * @return bool
     */
    public function isPost()
    {
        if($_SERVER['REQUEST_METHOD'] == 'POST')
            return true;
        return false;
    }


    /** 验证表单
     * @param array $config 表单验证的配置数组
     * @return bool
     */
    public function validate($config, ValidateComponent $validate=null)
    {
        $this->config = $config;

        if(!is_object($validate))
            $validate = new ValidateComponent($this);

        foreach($config as $key=>$cfg)
        {
            if(!empty($cfg['rules']))
            {
                $this->val = $this->post($cfg['field']);
                $this->label = $cfg['label'];
                $this->field = $cfg['field'];
                $rules = explode('|', $cfg['rules']);

                // 进行对规则逐一验证
                foreach($rules as $k=>$fn)
                {
                    $class = '';

                    if(substr($fn, 0, 1) == '*')
                    {
                        $controller = UrlComponent::getController();
                        eval('$class = new $controller();');
                        $fn = substr($fn, 1);
                    }
                    else 
                    {
                        $class = $validate;
                    }

                    $param = explode('<', $fn);

                    $function = $param[0];
                    $paramArr = array();
                    if(isset($param[1]))
                    {
                        $param = $param[1];
                        $paramArr = explode(',', $param);
                    }

                    // 回调函数
                    call_user_func_array(array($class, $function), $paramArr);
                }
            }
        }

        // 如果没有任何错误
        if(empty($this->errMsg))
            return true;
        else
            return false;
    }


    /** 显示对应字段出现的验证错误
     * @param string $field 错误字段
     * @param string $class 添加的css class名称
     * @return string
     */
    public function showError($field, $class='')
    {
        $flag = array_key_exists($field, $this->errMsg);

        $style = $flag ? '' : 'style="display:none"';

        $tagStart = '<span class='.$class.' '.$style.'>';
        $tagEnd = '</span>';

        return $tagStart . @$this->errMsg[$field] . $tagEnd;
    }


    /** 获取POST请求的控件的值
     * @param string $field
     * @return array|string
     */
    public function post($field)
    {
        $input = new InputComponent();
        return $input->post($field);
    }


    /** 设置表单对应控件的错误信息
     * @param string $msg  错误信息
     * @param string $field  字段
     */
    public function setError($msg)
    {
        // 记录对应的错误信息到错误数组中
        if (sizeof(@$this->errMsg[$this->field]) == 0)
            $this->errMsg[$this->field] = $msg;
    }

    /** 根据field获取label
     * @param string $field 表单控件的名称
     * @return bool
     */
    public function getLabelByField($field)
    {
        foreach ($this->config as $key => $value) 
        {
            if($value['field'] == $field)
                return $value['label'];  
        }

        return false;
    }


    /** 创建一个加密的字符串防跨站伪造请求
     * @return string
     */
    public function protectCsrf()
    {
        $this->csrf = sha1(rand(100, 1000) * time());
        $_SESSION[sha1('csrf')] = $this->csrf;
        return '<input type="hidden" name="csrf" value="'.$this->csrf.'"/>';
    }


    /** 检查当前是否是正常提交表单
     * @return bool
     */
    public function checkCsrf()
    {
        if($_SESSION[sha1('csrf')] == $_POST['csrf'])
            return true;

        return false;
    }


    /** 收集整个表单的有效数据
     * @param Model $model
     * @return array
     */
    public function create(Model $model)
    {
        if(method_exists($model, 'before'))
            $_POST = $model->before();

        $rs = array();
        $modelField = $model->getFields();
        foreach($modelField as $k=>$v)
        {
            if(array_key_exists($v, $_POST))
            {
                $rs[$v] = $this->post($v);
            }
        }

        return $rs;
    }


    public function allowLoad()
    {
        return true;
    }
}